using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;

/**
 * \author Nicolas Musset, Angry Ant (original version)
 * \date 2011-03-28
 * \class ComponentLister
 * \brief This class adds a window in the Unity editor that lists all
 *  components used in the current scene.
 */
public class ComponentLister : EditorWindow
{
    private SortedList<string, ArrayList> sets =
       new SortedList<string, ArrayList>();
    private SortedList<string, bool> foldedOuts =
       new SortedList<string, bool>();
    private Vector2 scrollPosition;

    /**
     * Menu entry for this window
     */
    [MenuItem("Component/Component Lister")]
    public static void MenuComponentLister()
    {
        EditorWindow window = GetWindow(typeof(ComponentLister));
        window.Show();
    }

    /**
     * Updates the list of components
     */
    public void UpdateList()
    {
        Object[] objects;
        objects = FindObjectsOfType(typeof(Component));

        sets.Clear();
        sets.Capacity = objects.Length;
        foldedOuts.Clear();
        foldedOuts.Capacity = objects.Length;

        foreach (Component component in objects)
        {
            string name = component.GetType().Name;
            if (!sets.ContainsKey(name))
            {
                sets[name] = new ArrayList();
                foldedOuts[name] = false;
            }

            (sets[name]).Add(component.gameObject);
        }
    }

    /**
     * Updates the list each time the hierarchy has been changed.
     * This also work when the scene is changed.
     */
    public void OnHierarchyChange()
    {
        UpdateList();
        Repaint();
    }

    /**
     * Override.
     */
    public void OnGUI()
    {
        GUILayout.BeginHorizontal(GUI.skin.GetStyle("Box"));
        GUILayout.Label("Components in scene:");
        GUILayout.FlexibleSpace();

        if (GUILayout.Button("Refresh"))
        {
            UpdateList();
        }
        GUILayout.EndHorizontal();

        scrollPosition = GUILayout.BeginScrollView(scrollPosition);

        foreach (string name in sets.Keys)
        {
            foldedOuts[name] =
          EditorGUILayout.Foldout(foldedOuts[name], name,
                                  new GUIStyle(EditorStyles.foldout)
                                  { fontStyle = FontStyle.Bold });
            if (foldedOuts[name])
            {
                foreach (GameObject gameObject in sets[name])
                {
                    if (GUILayout.Button(gameObject.name))
                    {
                        Selection.activeObject = gameObject;
                    }
                }
            }
        }

        GUILayout.EndScrollView();
    }
}